import styles from './index.module.scss';
import { Icon } from '@/components/Icon';
import NavBar from '@/components/NavBar';
import { useDispatch } from 'react-redux';
import { useParams } from 'react-router-dom';
import { useEffect, useRef, useState } from 'react';
import { clearArticleAction, getDetailByIdAction } from '@/store/action/articles';
import { useAppSelector } from '@/store';
import DOMPurify from 'dompurify';
import dayjs from 'dayjs';
import Skeleton from '@/components/Skeleton';

import hljs from 'highlight.js';
// 可以去项目下找到各种各样的主题风格
import 'highlight.js/styles/vs2015.css';
import classnames from 'classnames';
import NoComment from './components/NoComment';
import CommentItem from './components/CommentItem';
import { clearCommentsAction, getCommentsByIdAction } from '@/store/action/common';
import Loading from '@/components/Loading';
import CommentFooter from './components/CommentFooter';
import { Popup } from 'antd-mobile';
import CommentReply from './components/CommentReply';
import Share from './components/Share';
/*
  学习目标：使用弹出层，控制回复组件的显示与关闭
  点击回复，打开回复的弹出层
  1. reducer中设置originComment，设置初始值为{}
  2. 使用originComment.comm_id作为visible的值
  3. 定义actionType
  4. 定义action函数
  5. 点击回复，dispatch存入原始数据

*/
// 学习目标：组件卸载时-清除文章数据
export default function Article() {
  const [shareVisible, setShareVisible] = useState(false);
  const handleShowShare = () => setShareVisible(true);
  const handleCloseShare = () => setShareVisible(false);
  const { isLoading, commentList, originComment } = useAppSelector((state) => state.comment);
  const [authVisble, setAuthVisble] = useState(false);
  const commentRef = useRef<HTMLDivElement>(null);
  const authRef = useRef<HTMLDivElement>(null);
  const croRef = useRef<HTMLDivElement>(null);
  const dispatch = useDispatch();
  //  从redux中获取数据
  const { detail } = useAppSelector((state) => state.article);
  // 3.1 id是stiing类型
  // 3.2 通过useParams获取动态路由参数，要使用泛型函数的完整写法
  const { id } = useParams<{ id: string }>();
  useEffect(() => {
    dispatch(getDetailByIdAction(id));
  }, [dispatch, id]);
  // 3. 卸载时清除数据
  useEffect(() => {
    return () => {
      dispatch(clearArticleAction());
      // 3. 卸载时清除评论内容
      dispatch(clearCommentsAction());
    };
  }, [dispatch]);
  // 代码高亮
  useEffect(() => {
    // 配置 highlight.js
    hljs.configure({
      // 忽略未经转义的 HTML 字符
      ignoreUnescapedHTML: true,
    });

    // 获取到渲染正文的容器元素
    // 查找容器元素下符合 pre code 选择器规则的子元素，进行高亮
    const codes = document.querySelectorAll('.dg-html pre code');
    if (codes.length > 0) {
      return codes.forEach((el: any) => hljs.highlightElement(el));
    }

    // 查找容器元素下的 pre 元素，进行高亮
    const pre = document.querySelectorAll('.dg-html pre');
    if (pre.length > 0) {
      return pre.forEach((el) => hljs.highlightElement(el as any));
    }
  }, [detail.art_id]);
  // 监听滚动事件
  const scrollFn = () => {
    // console.log('滚动事件');
    const top = authRef.current?.getBoundingClientRect().top as number;
    // 判断作者信息的top值，如果大于17，不显示NavBar中的作者信息
    if (top < 17) {
      setAuthVisble(true);
    } else {
      setAuthVisble(false);
    }
  };
  useEffect(() => {
    // 💥 判断art_id不存在就不再往下执行
    if (!detail.art_id) return;
    // 类似闭包，声明一个外部变量，解决ts警告问题
    const ref1 = croRef.current;
    // 声明ref，监听DOM的滚动事件
    ref1?.addEventListener('scroll', scrollFn);
    return () => {
      // !是ts中的非空断言，表示一定不为null
      ref1!.removeEventListener('scroll', scrollFn);
    };
  }, [detail.art_id]);
  useEffect(() => {
    // 3. 根据文章id获取评论内容
    if (!detail.art_id) return;
    dispatch(getCommentsByIdAction({ type: 'a', source: detail.art_id }));
  }, [dispatch, detail.art_id]);
  // 1. 封装点击事件
  const handleScrollTop = () => {
    // 让Wrap去滚动
    // 5.完成计算逻辑
    if (!croRef.current) return;
    // 💥 offsetTop表示距离父级最高可滚动的高度
    // 💥 -50 表示不要被NavBar覆盖到
    croRef.current.scrollTop = commentRef.current!.offsetTop - 50;
  };
  return (
    <div className={styles.root}>
      <div className="root-wrapper">
        {/* 顶部导航栏 */}
        <NavBar right={<Icon type="icongengduo" />}>
          {/* 文章详情 */}
          {/*  放在NavBar组件标签之间 */}
          {authVisble ? (
            <div className="nav-author">
              <img src={detail.aut_photo} alt="" />
              <span className="name">{detail.aut_name}</span>
              <span className={classnames('follow', detail.is_followed ? 'followed' : '')}>
                {detail.is_followed ? '已关注' : '关注'}
              </span>
            </div>
          ) : (
            ''
          )}
        </NavBar>

        <div className="wrapper" ref={croRef}>
          {!!detail.art_id ? (
            <div className="article-wrapper">
              {/* 文章描述信息栏 */}
              <div className="header">
                <h1 className="title">{detail.title}</h1>

                <div className="info">
                  <span>{dayjs(detail.pubdate).format('YYYY-MM-DD')}</span>
                  <span>{detail.read_count} 阅读</span>
                  <span>{detail.comm_count} 评论</span>
                </div>

                <div className="author" ref={authRef}>
                  <img src={''} alt="" />
                  <span className="name">{detail.aut_name}</span>
                  <span className="follow">关注</span>
                </div>
              </div>

              {/* 文章正文内容区域 */}
              <div className="content">
                <div
                  className="content-html dg-html"
                  // html插入到div中
                  // DOMPurify防止xss攻击
                  dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(detail.content) }}
                ></div>
                <div className="date">发布文章时间：{dayjs().from(detail.pubdate)}</div>
                {/* ------------评论开始区域 💥 注意放在和date同级div */}
                <div className="divider"></div>
                <div className="comment" ref={commentRef}>
                  {/* 评论总览信息 */}
                  <div className="comment-header">
                    <span>全部评论（{detail.comm_count}）</span>
                    <span>{detail.like_count} 点赞</span>
                  </div>
                  {isLoading && <Loading />}
                  {/* 评论列表 */}
                  {detail.comm_count === 0 ? (
                    <NoComment />
                  ) : (
                    <div className="comment-list">
                      {commentList.map((item) => (
                        <CommentItem comment={item} key={item.com_id} />
                      ))}
                    </div>
                  )}
                </div>
              </div>
            </div>
          ) : (
            <Skeleton />
          )}
        </div>
      </div>
      <CommentFooter onShare={handleShowShare} onClick={handleScrollTop} articleData={detail} />
      {/* 0.设置一个右侧弹出层 ，通过原始的评论数据驱动的*/}
      {/* 6.com_id判断是否存在，显示或不显示右侧弹出层 */}
      <Popup visible={!!originComment.com_id} position="right" destroyOnClose>
        <CommentReply></CommentReply>
      </Popup>
      <Popup visible={shareVisible}>
        <Share onClose={handleCloseShare}></Share>
      </Popup>
    </div>
  );
}
